package com.upeoe.shiro.chapter1;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.apache.shiro.util.ThreadContext;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author ven_hxz
 * @create 2016-07-02 下午4:27
 */
public class BaseTutorial {
    private static transient final Logger log = LoggerFactory.getLogger(BaseTutorial.class);

    /**
     * Simple Apache Shiro Demo
     */
    @Test
    public void BaseDemo() {
        log.info("Apache Shiro Demo One");

        // 使用 IniSecurityManagerFactory 提取 shiro.ini 配置文件
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");

        // 解析 INI 配置文件并返回该配置文件的 SecurityManager 实例
        SecurityManager securityManager = factory.getInstance();

        // 设置 SecurityManager,和应用程序进行绑定
        // 在Web应用程序中,应该保存至 ServletContext 或 Spring等容器中
        SecurityUtils.setSecurityManager(securityManager);

        // 调用获取当前正在执行的用户, Subject 可以是一个用户,也可以是个第三方进程
        Subject currentUser = SecurityUtils.getSubject();

        UsernamePasswordToken token = new UsernamePasswordToken("root", "root");

        try {
            currentUser.login(token);
        } catch (AuthenticationException e) {
            e.printStackTrace();
        }

        //断言用户登录成功
        Assert.assertEquals(true, currentUser.isAuthenticated());
        currentUser.logout();
    }

    /**
     * 使用自定义单Realm实现进行验证
     */
    @Test
    public void testCustomRealm() {
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");
        SecurityManager securityManager = factory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);

        Subject currentUser = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken("root", "root");

        try {
            currentUser.login(token);
        } catch (AuthenticationException e) {
            e.printStackTrace();
        }

        //断言用户登录成功
        Assert.assertEquals(true, currentUser.isAuthenticated());
        currentUser.logout();
    }

    @Test
    public void testMultiCustomRealm() {
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-multi-realm.ini");
        SecurityManager securityManager = factory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);

        Subject currentUser = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken("guest", "guest");

        try {
            currentUser.login(token);
        } catch (AuthenticationException e) {
            e.printStackTrace();
        }

        Assert.assertEquals(true, currentUser.isAuthenticated());
        currentUser.logout();
    }

    @Test
    public void testJdbcRealm() {
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-jdbc-realm.ini");
        SecurityManager securityManager = factory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);

        Subject currentUser = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken("root", "root");

        try {
            currentUser.login(token);
        } catch (AuthenticationException e) {
            e.printStackTrace();
        }

        Assert.assertEquals(true, currentUser.isAuthenticated());
        currentUser.logout();
    }

    @After
    public void tearDown() {
        ThreadContext.unbindSubject();//退出时解除绑定Subject到线程 否则对下次测试造成影响
    }
}
